package net.retorx.util

import java.io.File
import java.awt.image.renderable.ParameterBlock
import java.awt.color.ColorSpace
import java.awt.image.{BufferedImageFilter, ColorConvertOp, BufferedImage}
import java.awt.{GraphicsEnvironment, GraphicsDevice, RenderingHints}
import javax.media.jai.operator.ScaleDescriptor
import javax.media.jai.{InterpolationBicubic, BorderExtender, JAI}

object ImageUtil {

	def getDimensions(file: File) = {
		val image = createBufferedImage(file)
		(image.getWidth, image.getHeight)
	}

	def resizeImage(renderedImage: BufferedImage, width: Int, height: Int) = {
		val hints = 0
		val thumbnail = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
		val graphics2d = thumbnail.createGraphics
		graphics2d.drawImage(renderedImage, 0, 0, width, height, null)
		graphics2d.dispose()

		thumbnail
	}

	def resizeConstrainedScaledImage(renderedImage: BufferedImage, maxWidth: Int, maxHeight: Int) = {
		val originalWidth = renderedImage.getWidth
		val originalHeight = renderedImage.getHeight

		val widthFactor = maxWidth.toFloat / originalWidth.toFloat
		val heightFactor = maxHeight.toFloat / originalHeight.toFloat

		val widthExceeds = originalWidth > maxWidth
		val heightExceeds = originalHeight > maxHeight

		val scaleFactor = calculateScaleFactor(widthFactor, heightFactor)
		if (scaleFactor > 0 && scaleFactor != 1) {
			scale(renderedImage, scaleFactor)
		} else {
			renderedImage
		}
	}

	private def scale(image: BufferedImage, scale: Float): BufferedImage = {
		val hints = new RenderingHints(JAI.KEY_BORDER_EXTENDER, BorderExtender.createInstance(BorderExtender.BORDER_COPY))
		val op = ScaleDescriptor.create(image, scale, scale, 0.toFloat, 0.toFloat, new InterpolationBicubic(0xf), hints)
		val scaledImage = op.getAsBufferedImage

		(scaledImage)
	}

	private def calculateScaleFactor(widthFactor: Float, heightFactor: Float): Float = {
		if (widthFactor > 0 && heightFactor > 0) {
			if (widthFactor < heightFactor) {
				widthFactor
			} else {
				heightFactor
			}
		} else if ((widthFactor > 0) != (heightFactor > 0)) {
			if (widthFactor < heightFactor) {
				heightFactor
			} else {
				widthFactor
			}
		} else {
			0.toFloat	
		}
	}

	private def createFuckingGraphicsEnv() = {
		val ge = GraphicsEnvironment.getLocalGraphicsEnvironment
		val gd = ge.getDefaultScreenDevice
		gd.getDefaultConfiguration
	}

	def savePNGImageFile(file: File, image: BufferedImage) = {
		val format = "png"
		val parameterBlock = new ParameterBlock()
		parameterBlock.addSource(image)
		parameterBlock.add(file.getAbsolutePath)
		parameterBlock.add(format)

		JAI.create("filestore", parameterBlock)
	}

	def desaturateImage(renderedImage: BufferedImage) = {
		val grayscaleOp = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), new RenderingHints(new java.util.HashMap()))
		grayscaleOp.filter(renderedImage, null) // null creates a new image :-/
	}

	def createBufferedImage(file: File) = {
		JAI.create("fileload", file.getAbsolutePath).getAsBufferedImage
	}

	def isImageFile(file: File) = {
		val name = file.getName
		name.endsWith("png") || name.endsWith("jpg")
	}

}